﻿var spFields = angular.module('spFields', []);

spFields.directive('spPeoplepicker', function () {
    var peoplePickerCounter = 1;
    //#region peoople picker schema
    var schema = {
        PrincipalAccountType: 'User,DL,SecGroup,SPGroup',
        SearchPrincipalSource: 15,
        ResolvePrincipalSource: 15,
        MaximumEntitySuggestions: 50
    };
    //#endregion

    return {
        require: '?ngModel',
        restrict: 'E',
        template: '<div class="sp-peoplepicker"></div>',
        link: function ($scope, $element, $attrs, ngModelController) {
            var pickerId = 'peoplepicker-' + peoplePickerCounter;
            peoplePickerCounter++;

            //We need this value to synchronize $render and OnValueChangedClientScript methods
            //In $render method we call People picker API to add users which fires OnValueChangedClientScript
            //We do not want that because it could lead to infinite loop: 
            //Model update from outside -> $render -> OnValueChangedClientScript -> update model -> $render -> ...
            var isRendering = false;
            var initPeoplePicker = function () {
                var templateTopDiv = $element.children('div');
                if (!templateTopDiv.attr('id')) {
                    templateTopDiv.attr('id', pickerId);
                }

                schema.AllowMultipleValues = ($element.attr('multiple')) ? true : false;
                schema.OnValueChangedClientScript = function (topElementId, resolvedUsers) {
                    if (isRendering)
                        return;
                    var picker = SPClientPeoplePicker.SPClientPeoplePickerDict[topElementId];
                    var currentEditorValue = picker.GetCurrentEditorValue();
                    if (currentEditorValue && currentEditorValue.length !== 0) {
                        resolvedUsers.push({
                            AutoFillDisplayText: currentEditorValue,
                            DisplayText: currentEditorValue,
                            IsResolved: false,
                            Resolved: false,
                            Key: currentEditorValue
                        });
                    }
                    if ($scope.$$phase) {
                        ngModelController.$setViewValue(resolvedUsers);
                    }
                    else {
                        $scope.$apply(function () {
                            ngModelController.$setViewValue(resolvedUsers);
                        });
                    }
                }

                SPClientPeoplePicker_InitStandaloneControlWrapper(pickerId, null, schema);
            }();

            ngModelController.$isEmpty = function (value) {
                return !value || value.length === 0;
            };

            ngModelController.$parsers.unshift(function (value) {
                if (value) {
                    var spUsers = [];
                    for (var i = 0; i < value.length; i++) {
                        if (!value[i].IsResolved) {
                            ngModelController.$setValidity('failedToResolve', false);
                            return undefined;
                        }
                        spUsers.push({
                            Title: value[i].Title,
                            Name: value[i].Key
                        });
                    }
                    ngModelController.$setValidity('failedToResolve', true);
                    return spUsers;
                }
                else {
                    ngModelController.$setValidity('failedToResolve', true);
                    return [];
                }
            });

            ngModelController.$formatters.push(function (value) {
                var toPickerObject = function (v) {
                    return {
                        AutoFillDisplayText: v.Title,
                        AutoFillKey: v.Name,
                        AutoFillSubDisplayText: "",
                        DisplayText: v.Title,
                        EntityType: "User",
                        IsResolved: true,
                        Key: v.Name,
                        ProviderDisplayName: "Tenant",
                        ProviderName: "Tenant",
                        Resolved: true
                    };
                }

                if (value) {
                    var peoplePickerObjects = [];
                    if ($.isArray(value)) {
                        for (var i = 0; i < value.length; i++) {
                            peoplePickerObjects.push(toPickerObject(value[i]));
                        }
                    }
                    else {
                        peoplePickerObjects.push(toPickerObject(value));
                    }
                    return peoplePickerObjects;
                }
                else {
                    return [];
                }
            });

            ngModelController.$render = function () {
                var clearPicker = function (picker) {
                    var currentUserCount = picker.TotalUserCount;
                    for (var i = 0; i < currentUserCount; i++) {
                        picker.DeleteProcessedUser(null);
                    }
                }

                var viewValue = ngModelController.$viewValue;
                if (viewValue) {
                    isRendering = true;
                    var picker = SPClientPeoplePicker.SPClientPeoplePickerDict[pickerId + '_TopSpan'];
                    clearPicker(picker);
                    for (var i = 0; i < viewValue.length; i++) {
                        picker.AddProcessedUser(viewValue[i], true);
                    }
                    isRendering = false;
                }
            };
        }
    };
});

spFields.directive('spLookup', function () {

});

spFields.directive('spTaxonomypicker', function () {
    var taxonmyPickerCounter = 1;
    return {
        require: '?ngModel',
        restrict: 'E',
        template: '<input type="hidden" />',
        link: function ($scope, $element, $attrs, ngModelController) {

            var hiddenInputId = 'taxonomypicker-hiddeninput-' + taxonmyPickerCounter;
            taxonmyPickerCounter++;

            var hiddenInput = $element.find('input');
            if (!hiddenInput.attr('id')) {
                hiddenInput.attr('id', hiddenInputId);
            }

            $element.addClass('app-loading');
            var isLoaded = false;
            var initTaxonomyPicker = function () {
                if (isLoaded)
                    return;

                var context = new SP.ClientContext($scope.AppWebUrl);
                $(hiddenInput).taxpicker({
                    isMulti: $attrs.ismulti,
                    termSetId: $attrs.termsetid
                }, context, function () {
                    var taxPicker = $(hiddenInput).data('taxPickerInstance');

                    var values = taxPicker.getValidatedTerms();
                    $.each(values, function (k, v) {
                        v.Resolved = true;
                    });

                    var currentEditorValue = taxPicker.getEditorText();
                    if (currentEditorValue && currentEditorValue.length !== 0) {
                        values.push({
                            Name: currentEditorValue,
                            Id: "",
                            Resolved: false
                        });
                    }
                    if ($scope.$$phase) {
                        ngModelController.$setViewValue(values);
                    }
                    else {
                        $scope.$apply(function () {
                            ngModelController.$setViewValue(values);
                        });
                    }
                });
                $element.removeClass('app-loading');
                isLoaded = true;
                ngModelController.$render();
            };

            var verifyRequiredAttributes = function () {
                return ($attrs.termsetid && !$attrs.termsetid.length !== 0) && ($attrs.ismulti !== undefined);
            }

            if (verifyRequiredAttributes()) {
                initTaxonomyPicker();
            }
            else {
                var stopWatch = $scope.$watch(function () {
                    return [$attrs.termsetid, $attrs.ismulti];
                }, function () {
                    if (verifyRequiredAttributes()) {
                        initTaxonomyPicker();
                        stopWatch();
                    }
                }
                , true);
            }

            ngModelController.$isEmpty = function (value) {
                return !value || value.length === 0;
            };

            ngModelController.$parsers.unshift(function (value) {
                if (value) {
                    var taxonomyValues = [];
                    for (var i = 0; i < value.length; i++) {
                        if (!value[i].Resolved) {
                            ngModelController.$setValidity('failedToResolve', false);
                            return undefined;
                        }
                        taxonomyValues.push({
                            "Label": value[i].Name,
                            "TermGuid": value[i].Id,
                            "WssId": "-1"
                        });
                    }
                    ngModelController.$setValidity('failedToResolve', true);
                    return taxonomyValues;
                }
                else {
                    ngModelController.$setValidity('failedToResolve', true);
                    return [];
                }
            });

            ngModelController.$formatters.push(function (value) {
                var toTermObject = function (v) {
                    return {
                        "Id": v.TermGuid,
                        "Name": v.Label
                    };
                }
                if (value) {
                    var tags = [];
                    if ($.isArray(value)) {
                        for (var i = 0; i < value.length; i++) {
                            tags.push(toTermObject(value[i]));
                        }
                    }
                    else {
                        tags.push(toTermObject(value));
                    }

                    return tags;
                }
                else {
                    return [];
                }
            });

            ngModelController.$render = function () {
                if (!isLoaded)
                    return;

                var viewValue = ngModelController.$viewValue;
                if (viewValue) {
                    var taxPicker = $(hiddenInput).data('taxPickerInstance');
                    taxPicker.clearSelection();
                    $.each(viewValue, function (k, v) {
                        taxPicker.addTerm(v);
                    });
                }
            };
        }
    };
});

